package com.information.manage.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.information.manage.basic.audit.constant.AuditTaskStatusEnum;
import com.information.manage.basic.audit.model.dto.InitAuditTaskDataDto;
import com.information.manage.basic.audit.model.entity.AuditModelDO;
import com.information.manage.basic.audit.service.AuditModelService;
import com.information.manage.basic.audit.service.AuditTaskService;
import com.information.manage.basic.common.result.Result;
import com.information.manage.basic.common.token.TokenUtils;
import com.information.manage.basic.common.utils.ConvertUtils;
import com.information.manage.basic.common.utils.FileUtils;
import com.information.manage.basic.mapper.DepartmentMapper;
import com.information.manage.basic.model.entity.DepartmentDO;
import com.information.manage.basic.model.vo.LoginUserInfoVO;
import com.information.manage.basic.service.SysUserService;
import com.information.manage.dao.ManuMapper;
import com.information.manage.model.entity.ManuDO;
import com.information.manage.model.query.AddManuQuery;
import com.information.manage.model.query.ManuQuery;
import com.information.manage.model.query.UpdateManuQuery;
import com.information.manage.model.vo.StatisticDepartmentUploadVO;
import com.information.manage.service.CommonService;
import com.information.manage.service.ManuService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executor;
import java.util.stream.Collectors;

@Slf4j
@Service
public class ManuServiceImpl extends ServiceImpl<ManuMapper, ManuDO>  implements ManuService {

    @Autowired
    private ManuMapper manuMapper;

    @Autowired
    private SysUserService sysUserService;

    @Autowired
    private CommonService commonService;

    @Autowired
    private FileUtils fileUtils;

    @Autowired
    private AuditModelService auditModelService;

    @Resource(name = "taskExecutor")
    private Executor taskExecutor;

    @Autowired
    private AuditTaskService auditTaskService;

    @Autowired
    private DepartmentMapper departmentMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<Long> add(AddManuQuery addManuQuery, HttpServletRequest request, List<MultipartFile> enclosures) {
        Integer userId = TokenUtils.getUserId(StringUtils.isEmpty(request.getHeader("token")) ? request.getAttribute("token").toString() : request.getHeader("token"));
        ManuDO manuDO = new ManuDO();
        BeanUtils.copyProperties(addManuQuery, manuDO);
        LoginUserInfoVO userInfo = sysUserService.getUserInfo(userId);
        Assert.isTrue(userInfo != null, "用户不存在");
        manuDO.setCreateUserId(userInfo.getId());
        manuDO.setCreateUserName(userInfo.getName());
        Integer departmentId = userInfo.getDepartmentId();
        if (departmentId != null) manuDO.setDepartmentId(departmentId);
        String departmentName = userInfo.getDepartmentName();
        if (StringUtils.isNotEmpty(departmentName)) manuDO.setDepartmentName(departmentName);
        Date date = new Date();
        manuDO.setCreateTime(date);
        manuDO.setUpdateTime(date);
        if (CollectionUtils.isNotEmpty(enclosures)){
            String path = commonService.handleAddEnclosures(enclosures);
            manuDO.setEnclosurePath(path);
        }
        manuDO.setDeleteData(0);
        AuditModelDO auditModelDO = auditModelService.readApplyAuditTemplate();
        boolean isAudit = false;
        if (auditModelDO != null){
            manuDO.setAuditStatus(AuditTaskStatusEnum.IN_PROCESS.getStatus());
            isAudit = true;
        }else {  // 不存在审核模板 直接通过
            manuDO.setAuditStatus(AuditTaskStatusEnum.PASS.getStatus());
        }
        manuMapper.insert(manuDO);
        // 加入审核
        if (isAudit) sendAuditTask(auditModelDO, manuDO, userInfo);
        return Result.ok(manuDO.getId());
    }

    private void sendAuditTask(AuditModelDO auditModelDO, ManuDO manuDO, LoginUserInfoVO userInfo){
        InitAuditTaskDataDto initAuditTaskDataDto = new InitAuditTaskDataDto();
        initAuditTaskDataDto.setMainId(manuDO.getId().toString());
        initAuditTaskDataDto.setTitle(manuDO.getTitle());
        initAuditTaskDataDto.setUserId(manuDO.getCreateUserId().toString());
        initAuditTaskDataDto.setUserName(manuDO.getCreateUserName());
        auditTaskService.initAuditTask(auditModelDO, initAuditTaskDataDto, userInfo);
    }

    @Override
    public Result<Boolean> updateAf(HttpServletRequest request, UpdateManuQuery updateManuQuery, List<MultipartFile> enclosures) {
        Integer userId = TokenUtils.getUserId(StringUtils.isEmpty(request.getHeader("token")) ? request.getAttribute("token").toString() : request.getHeader("token"));
        LoginUserInfoVO userInfo = sysUserService.getUserInfo(userId);
        Assert.isTrue(userInfo != null, "用户不存在");
        Long id = updateManuQuery.getId();
        ManuDO manuDO = manuMapper.selectById(id);
        Assert.isTrue(manuDO != null, "不存在该记录");
        Assert.isTrue(manuDO.getDeleteData() == 0, "该记录已被删除，修改失败");
        ManuDO updateManuDO = ConvertUtils.sourceToTargetIfNotNull(updateManuQuery, ManuDO.class);
        if (CollectionUtils.isNotEmpty(enclosures)){
            // 如果存在附件，处理附件路径
            String oldPath = manuDO.getEnclosurePath();
            if (oldPath != null) { // 添加空值检查
                File file = new File(oldPath);
                if (file.isDirectory()) {
                    boolean delete = fileUtils.deleteDir(oldPath);
                    log.info("------id={}, 镜像文件删除结果={}", manuDO.getId(), delete);
                } else {
                    file.delete();
                }
                String path = commonService.handleAddEnclosures(enclosures);
                updateManuDO.setEnclosurePath(path);
            } else {
                log.warn("记录的附件路径为空，跳过删除操作");
            }
        }
        updateManuDO.setUpdateTime(new Date());
        AuditModelDO auditModelDO = auditModelService.readApplyAuditTemplate();
        boolean isAudit = false;
        if (auditModelDO != null){
            manuDO.setAuditStatus(AuditTaskStatusEnum.IN_PROCESS.getStatus());
            updateManuDO.setAuditStatus(AuditTaskStatusEnum.IN_PROCESS.getStatus());
            isAudit = true;
        }else {  // 不存在审核模板 直接通过
            updateManuDO.setAuditStatus(AuditTaskStatusEnum.PASS.getStatus());
        }
        manuMapper.updateById(updateManuDO);
        // 修改需要先撤销之前的任务再添加新任务
        auditTaskService.cancelProcessAuditTasks(updateManuDO.getId().toString());
        // 加入审核
        String title = updateManuQuery.getTitle();
        String author = updateManuQuery.getAuthor();
        String content = updateManuQuery.getContent();
        String origin = updateManuQuery.getOrigin();
        if (StringUtils.isNotEmpty(title)){
            manuDO.setTitle(title);
        }
        if (StringUtils.isNotEmpty(author)){
            manuDO.setAuthor(author);
        }
        if (StringUtils.isNotEmpty(content)){
            manuDO.setContent(content);
        }
        if (StringUtils.isNotEmpty(origin)){
            manuDO.setOrigin(origin);
        }
        if (isAudit) sendAuditTask(auditModelDO, manuDO, userInfo);
        return Result.ok(Boolean.TRUE);
    }


    @Override
    public Result<Boolean> delete(List<Long> ids) {
        int update = manuMapper.update(null, new LambdaUpdateWrapper<ManuDO>()
                .in(ManuDO::getId, ids)
                .set(ManuDO::getDeleteData, 1));
        if (update == ids.size()) {
            // 删除成功后需要处理删除文件
            taskExecutor.execute(() -> {
                List<ManuDO> manuDOS = manuMapper.selectList(new LambdaQueryWrapper<ManuDO>().in(ManuDO::getId, ids));
                for (ManuDO manuDO : manuDOS) {
                    if (manuDO.getDeleteData() == 1){  // 再次验证是否已删除
                        String enclosurePath = manuDO.getEnclosurePath();
                        File file = new File(enclosurePath);
                        if (file.isDirectory()) {
                            boolean delete = fileUtils.deleteDir(enclosurePath);
                            log.info("------id：{} 文件删除：{}", manuDO.getId(), delete);
                        }else {
                            file.delete();
                        }
                        // 清理审核中的任务
                        auditTaskService.cancelProcessAuditTasks(manuDO.getId().toString());
                    }
                }
            });
            return Result.ok(Boolean.TRUE);
        }
        return Result.fail("删除失败");
    }

    @Override
    public Result<List<String>> getFileEnclosurePath(Long id) {
        ManuDO manuDO = manuMapper.selectById(id);
        if (manuDO == null || manuDO.getDeleteData() != 0) {
            return Result.fail("该数据已被删除");
        }
        String enclosurePath = manuDO.getEnclosurePath();
        if (StringUtils.isEmpty(enclosurePath)) return Result.ok();
        return commonService.getVisitPath(enclosurePath);
    }

    @Override
    public Result<Page<ManuDO>> findPage(HttpServletRequest request, ManuQuery manuQuery) {
        Integer userId = TokenUtils.getUserId(StringUtils.isEmpty(request.getHeader("token")) ? request.getAttribute("token").toString() : request.getHeader("token"));
        Assert.isTrue(userId != null, "未找到用户id");
        Page<ManuDO> manuDOS = manuMapper.queryPage(new Page<>(manuQuery.getCurPage(), manuQuery.getPageSize())
                , manuQuery.getTitle(),manuQuery.getDeleteData(), manuQuery.getStartTime(), manuQuery.getEndTime(), manuQuery.getAuditStatus()
            , userId, manuQuery.getDepartmentId());
        return Result.ok(manuDOS);
    }

    @Override
    public ManuDO findById(Long id) {
        return manuMapper.selectById(id);
    }

    @Override
    public Result<List<StatisticDepartmentUploadVO>> statisticDepartmentUpload(Integer days, Integer auditStatus) {
        List<StatisticDepartmentUploadVO> statisticDepartmentUploadVOS = manuMapper.statisticDepartmentUpload(days == null ? 7 : days, auditStatus);
        if (CollectionUtils.isNotEmpty(statisticDepartmentUploadVOS)){
            List<Integer> departmentIds = statisticDepartmentUploadVOS.stream().map(StatisticDepartmentUploadVO::getDepartmentId).collect(Collectors.toList());
            // 找到最新的部门信息
            Map<Integer, String> collect = departmentMapper.selectBatchIds(departmentIds).stream().collect(Collectors.toMap(k -> k.getId(), DepartmentDO::getName));
            for (StatisticDepartmentUploadVO statisticDepartmentUploadVO : statisticDepartmentUploadVOS) {
                Integer departmentId = statisticDepartmentUploadVO.getDepartmentId();
                String name = collect.get(departmentId);
                if (StringUtils.isNotEmpty(name)){
                    statisticDepartmentUploadVO.setDepartmentName(name);
                }else {
                    statisticDepartmentUploadVO.setDepartmentName("临时部门");
                }
            }
            return Result.ok(statisticDepartmentUploadVOS);
        }
        return Result.ok(new ArrayList<>());
    }

}
